# !/usr/bin/python3
# -*- coding: utf-8 -*-
# @Time    : 2021/12/8 11:40
# @Author  : zuodengbo
# @Email   : zuodb@amoydx.com
# @File    : new_views
# @Software: PyCharm
from pymysql import DatabaseError
from sanic.log import logger
from sanic.views import HTTPMethodView
from sanic_openapi.openapi3 import openapi
from sanic_validation import validate_json, validate_args
from tortoise.query_utils import Q

from user.models import *
from user.schemas import *
from utils.const import UserStatus
from utils.decorator import login_required
from utils.page_helper import page_helper
from utils.resp_code import *


class UserView(HTTPMethodView):
    decorators = [login_required]
    
    async def get(self, request):
        """
        查询用户
        :param request:
        :return:
        """
        user_id = request.args.get('id')
        keyword = request.args.get("keyword")
        offset, limit = page_helper(request)
        _init_data = dict()
        user_info = list()
        try:
            if user_id:
                user = await User.filter(id=user_id).first()
                _init_data["username"] = user.username
                _init_data["name"] = user.name
                _init_data["phone"] = user.phone
                _init_data["email"] = user.email
                _init_data["age"] = user.age
                _init_data["gender"] = user.gender
                _init_data["birthday"] = user.birthday
                _init_data["address"] = user.address
                return make_success_response(data=_init_data)
            else:
                if keyword:
                    # contains需要精确大小写，icontains忽略大小写
                    condition = Q(Q(id__icontains=keyword) | Q(username__icontains=keyword)) \
                                | Q(name__icontains=keyword) | Q(email__icontains=keyword) \
                                | Q(phone__icontains=keyword) | Q(age__icontains=keyword) \
                                | Q(gender__icontains=keyword) | Q(address__icontains=keyword) \
                                | Q(remark__icontains=keyword) | Q(status__icontains=keyword)
                    users = await User.filter(condition).all().order_by("id").offset(offset).limit(limit).values()
                    total = await User.filter(condition).all().count()
                else:
                    users = await User.filter().all().order_by("id").offset(offset).limit(limit).values()
                    total = await User.filter().all().count()
                for user in users:
                    _init_data = json.loads(json.dumps(user, default=str))
                    user_info.append(_init_data)
                return make_success_response(data=user_info, total=total, query_total=users.__len__())
        except Exception as e:
            msg = "Query users info failed:{} line: {}".format(e, e.__traceback__.tb_lineno)
            logger.error(msg)
            return make_error_response(code=RespCode.QUERY_FAILED, message=msg)

    @validate_json(ADD_USER_SCHEMA)
    async def post(self, request):
        """
        添加用户
        :param request:
        :return:
        """
        logger.info("User Register Data: {}".format(request.json))
        username = request.json.get("username")
        # 传入md5之后的密码 如：123456 -> e10adc3949ba59abbe56e057f20f883e
        name = request.json.get("name")
        password = request.json.get("password")
        phone = request.json.get("phone")
        email = request.json.get("email")
        
        # 查询用户名、手机号、邮箱是否存在，不存在再创建，已禁用账户不再重新创建
        query_user = await User.filter(
            Q(Q(username=username) | Q(phone=phone) | Q(email=email))).first()
        if query_user:
            if query_user.status == UserStatus.enabled:
                if query_user.username == username:
                    msg = "The username: {} already exist !".format(username)
                    logger.warning(msg)
                    return make_error_response(code=RespCode.USERNAME_ALREADY_EXISTS, message=msg)
                elif query_user.phone == phone:
                    msg = "The phone number: {} had been registered !".format(phone)
                    logger.warning(msg)
                    return make_error_response(code=RespCode.PHONE_REGISTERED, message=msg)
                elif query_user.email == email:
                    msg = "The email: {} had been registered !".format(username)
                    logger.warning(msg)
                    return make_error_response(code=RespCode.EMAIL_REGISTERED, message=msg)
            else:
                if query_user.username == username:
                    msg = "The username: {} had been abandoned !".format(username)
                    logger.warning(msg)
                    return make_error_response(code=RespCode.USERNAME_ABANDONED, message=msg)
                elif query_user.phone == phone:
                    msg = "The user associated with the phone number: {} had been abandoned !".format(phone)
                    logger.warning(msg)
                    return make_error_response(code=RespCode.PHONE_DISABLED, message=msg)
                elif query_user.email == email:
                    msg = "The user associated with the email: {} had been abandoned !".format(username)
                    logger.warning(msg)
                    return make_error_response(code=RespCode.EMAIL_DISABLED, message=msg)

        try:
            user = await User.create(
                username=username,
                name=name,
                password=password,
                phone=phone,
                email=email,
                update_time=time_now()
            )
            msg = "Add user:{} success !".format(username)
            logger.debug(msg)

        except DatabaseError as e:
            msg = "Database error：{}".format(e, e.__traceback__.tb_lineno)
            logger.error(msg)
            return make_error_response(code=RespCode.DATABASE_ERROR, message=msg)
        except Exception as e:
            msg = "Add user: {} info failed：{}, line: {}".format(username, e, e.__traceback__.tb_lineno)
            logger.error(msg)
            # rollback()
            return make_error_response(code=RespCode.USER_REGISTER_FAILED, message=msg)

        _init_data = dict()
        _init_data["username"] = username
        _init_data["user_id"] = user.id

        return make_success_response(message="Add user success !", data=_init_data)

    @validate_json(USER_SCHEMA)
    async def put(self, request):
        """
        修改用户（整体数据传回）
        :param request:
        :return:
        """
        logger.info("Modify my info data: {}".format(request.json))

        # 从token中解析用户
        user_id = request.json.get("id")
        phone = request.json.get("phone")
        email = request.json.get("email")
        age = request.json.get("age", None)
        gender = request.json.get("gender", None)
        birthday = request.json.get("birthday", None)
        address = request.json.get("address", None)
        remark = request.json.get("remark", None)
        if not birthday:
            birthday = time_now().strftime("%Y-%m-%d")

        try:
            await User.filter(id=user_id).update(
                phone=phone,
                email=email,
                age=age,
                gender=gender,
                birthday=birthday,
                remark=remark,
                address=address,
                update_time=time_now())
        except DatabaseError as e:
            msg = "Database error:{}, line:{}".format(e, e.__traceback__.tb_lineno)
            logger.warning(msg)
            return make_error_response(code=RespCode.DATABASE_ERROR, message=msg)
        except Exception as e:
            msg = "Other failure occurred when update user info, error: {}, line:{}". \
                format(e, e.__traceback__.tb_lineno)
            logger.warning(msg)
            return make_error_response(code=RespCode.UNKNOWN_FAILURE, message=msg)

        return make_success_response(message="Modify User Info Success !")

    @validate_args(COMMON_ID_SCHEMA)
    async def delete(self, request):
        """
        删除用户
        :param request:
        :return:
        """
        user_id = request.args.get("id")
        try:
            await User.filter(id=user_id).update(status=UserStatus.disabled)
            return make_success_response(message="Delete User Success")
        except Exception as e:
            msg = "When delete user, exception occurred: {}".format(e)
            logger.error(msg)
            return make_error_response(code=RespCode.UNKNOWN_FAILURE, message=msg)

    @validate_json(COMMON_ID_SCHEMA)
    async def patch(self, request):
        """
        修改用户(只修改有变动的字段)
        :param request:
        :return:
        """
        json_data = request.json
        user_id = json_data.get("id")
        json_data.pop("id")
        try:
            await User.filter(id=user_id).update(**json_data)
            return make_success_response(message="Update User Info Success")
        except Exception as e:
            msg = "When delete user, exception occurred: {}".format(e)
            logger.error(msg)
            return make_error_response(code=RespCode.UNKNOWN_FAILURE, message=msg)
